<!-- 菜单栏旁边的展示内容区域内的：用户列表组件 -->
<template>
  <!-- 用户列表组件 -->
  <div class="users_cont">
    <!-- 导航面包屑区域 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>用户管理</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片展示内容区域 -->
    <el-card class="box-card">
      <!-- 栅格布局 -->
      <el-row :gutter="20">
        <el-col :span="10">
          <el-input placeholder="请输入内容" v-model="usersList.query" clearable @clear="getUsersList">
            <el-button slot="append" icon="el-icon-search" @click="getUsersList"></el-button>
          </el-input>
        </el-col>
        <el-col :span="6">
          <el-button type="primary" @click="dialogUser">添加用户</el-button>
        </el-col>
      </el-row>
      <!-- 用户列表展示表格 -->
      <el-table :data="User_List" style="width: 100%" stripe border>
        <!-- 设置表格序号 type="index" -->
        <el-table-column type="index"></el-table-column>
        <el-table-column prop="username" label="姓名">
        </el-table-column>
        <el-table-column prop="mobile" label="电话" min-width="100">
        </el-table-column>
        <el-table-column prop="email" label="邮箱" min-width="110">
        </el-table-column>
        <el-table-column prop="role_name" label="角色">
        </el-table-column>
        <el-table-column label="状态">
          <!-- 接收作用域数据需要放置 template模板 写上属性 slot-scope="scope" -->
          <template slot-scope="scope">
            <!-- {{scope.row}}能打印当前作用域中的对应的数据 -->
            <el-switch v-model="scope.row.mg_state" @change="mgState(scope.row)">
            </el-switch>
          </template>
        </el-table-column>
        <el-table-column prop="" label="操作" min-width="180">
          <template slot-scope="scope">
            <!-- {{scope.row}}能打印当前作用域中的对应的数据 -->
            <div class="table_but">
              <!-- 角色分配 -->
              <el-tooltip class="item" effect="dark" content="分配角色" placement="left" :enterable="false"
                :hide-after="800">
                <el-button type="warning" icon="el-icon-setting" size="mini" @click="allotBut(scope.row)"></el-button>
              </el-tooltip>
              <!-- 修改 -->
              <el-button type="primary" icon="el-icon-edit" size="mini" @click="alterBut(scope.row)"></el-button>
              <!-- 删除 -->
              <el-button type="danger" icon="el-icon-delete" size="mini" @click="removeBut(scope.row)"></el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页按钮 -->
      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
        :current-page="usersList.pagenum" :page-sizes="[1, 2, 5, 10]" :page-size="usersList.pagesize"
        layout="total, sizes, prev, pager, next, jumper" :total="UserLength" :background="true">
      </el-pagination>
    </el-card>
    <!-- 添加用户对话框区域 -->
    <el-dialog title="添加用户" :visible.sync="addDialogVisible" width="50%" @closed="addResetFields"
      :close-on-click-modal="false">
      <!-- 用户信息表单 -->
      <el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="120px" class="add_form">
        <el-form-item label="用户账户" prop="username">
          <el-input v-model="addForm.username"></el-input>
        </el-form-item>
        <el-form-item label="用户密码" prop="password">
          <el-input v-model="addForm.password"></el-input>
        </el-form-item>
        <el-form-item label="手机号码" prop="mobile">
          <el-input v-model="addForm.mobile"></el-input>
        </el-form-item>
        <el-form-item label="电子邮箱" prop="email">
          <el-input v-model="addForm.email"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addResetFields()">取 消</el-button>
        <el-button type="primary" @click="addUsers">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 操作块-修改用户按钮区域 -->
    <el-dialog title="修改用户" :visible.sync="alterDialogVisible" width="50%" :close-on-click-modal="false"
      @close="alterResetFields">
      <el-form ref="alterFormRef" :model="alterUser" :rules="addFormRules" label-width="80px" class="add_form">
        <el-form-item label="用户账户">
          <el-input v-model="alterUser.username" disabled></el-input>
        </el-form-item>
        <el-form-item label="手机" prop="mobile">
          <el-input v-model="alterUser.mobile"></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="alterUser.email"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="alterResetFields">取 消</el-button>
        <el-button type="primary" @click="alterUserOk">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 操作块-分配角色按钮区域 -->
    <el-dialog title="分配角色" :visible.sync="allotDialogVisible" width="50%" :before-close="allotHandleClose"
      :close-on-click-modal="false">
      <!-- 分配角色的表单区域 -->
      <el-form ref="allotFormRef" :model="allotForm" label-width="80px" class="add_form">
        <el-form-item label="用户名称">
          <el-input v-model="allotForm.username" disabled></el-input>
        </el-form-item>
        <el-form-item label="角色名称">
          <el-input v-model="allotForm.role_name" disabled></el-input>
        </el-form-item>
        <div>
          <p class="allot_p">重新选择角色：</p>
          <el-select v-model="allotValue" placeholder="请选择">
            <el-option v-for="item in allotRolesList" :key="item.id" :label="item.roleName" :value="item.id">
            </el-option>
          </el-select>
        </div>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="allotHandleClose">取 消</el-button>
        <el-button type="primary" @click="saveRoleInfo">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
  export default {
    data() {
      //验证手机号码的规则
      var checkMobile = (rule, value, cb) => {
        const regMobile = /^1[34578]\d{9}$/
        if (!value) {
          //返回一个错误提示
          cb(new Error('请输入手机号码！'))
        } else {
          if (regMobile.test(value)) {
            return cb()
          }
          cb(new Error('请输入合法的手机号码！'))
        }
      }
      // 验证用户邮箱的规则
      var checkEmail = (rule, value, cb) => {
        const regEmail = /^\w+@\w+(\.\w+)+$/
        if (!value) {
          return cb()
        } else {
          if (regEmail.test(value)) {
            return cb()
          }
          cb(new Error('请输入合法的电子邮箱！'))
        }
      }
      return {
        // 获取用户列表参数 1：查询参数（搜索框、可为空） 2：当前页码 3：每页显示条数
        usersList: {
          query: '',
          pagenum: 1,
          pagesize: 5
        },
        // 存放获取的用户列表
        User_List: [],
        // 用户列表总记录数
        UserLength: 0,
        // 添加用户对话框的显示
        addDialogVisible: false,
        // 添加用户信息表单
        addForm: {
          username: '',
          password: '',
          mobile: '',
          email: ''
        },
        // 添加用户信息表单验证
        addFormRules: {
          // 用户账户
          username: [{
              // 文字前面是否出现不可为空符号*
              required: true,
              message: "请输入用户账户！",
              trigger: "blur"
            },
            {
              min: 3,
              max: 10,
              message: '长度在 3 到 10 个字符',
              trigger: 'blur'
            }
          ],
          // 用户密码
          password: [{
              required: true,
              message: "请输入用户密码！",
              trigger: "blur"
            },
            {
              min: 5,
              max: 10,
              message: '长度在 6 到 13 个字符',
              trigger: 'blur'
            }
          ],
          // 手机号码
          mobile: [{
            required: true,
            validator: checkMobile,
            trigger: 'blur'
          }],
          // 电子邮箱
          email: [{
            validator: checkEmail,
            trigger: 'blur'
          }],

        },
        // 修改用户弹窗显示与否
        alterDialogVisible: false,
        // 修改用户的表单信息:
        alterUser: {
          id: '',
          username: '',
          mobile: '',
          email: ''
        },
        // 操作块-分配角色按钮弹出对话框的显示与隐藏
        allotDialogVisible: false,
        // 操作块-分配角色的表单区域
        allotForm: {},
        // 分配角色-所有角色的数据列表下拉展示
        allotRolesList: [],
        // 分配角色-新选择的角色id（通过下拉选择）
        allotValue: ''
      }
    },
    created() {
      this.getUsersList()
    },
    methods: {
      // 获取用户列表
      async getUsersList() {
        let {
          data: res
        } = await this.$http.get('users', {
          params: this.usersList
        })
        if (res.meta.status === 200) {
          this.User_List = res.data.users
          this.UserLength = res.data.total
        } else {
          this.$message.error("获取用户列表失败！")
        }
      },


      // 处理页码大小：几条/页
      handleSizeChange(val) {
        this.usersList.pagesize = val
        this.getUsersList()
      },


      // 当前页变动：第几页
      handleCurrentChange(val) {
        this.usersList.pagenum = val
        this.getUsersList()
      },


      // 监听switch开关对用户状态的改变
      async mgState(user) {
        let {
          data: res
        } = await this.$http.put(`users/${user.id}/state/${user.mg_state}`)
        if (res.meta.status === 200) {
          this.$message.success("更新用户状态成功！")
        } else {
          // 更新失败，页面状态也不便
          user.mg_state = !user.mg_state
          this.$message.error("更新用户状态失败！")
        }

      },


      // 点击添加用户按钮
      dialogUser() {
        this.addDialogVisible = true
      },


      // 添加用户表单的取消按钮（重置）
      addResetFields() {
        this.addDialogVisible = false
        // addFormRef：Html内ref定义的
        this.$refs.addFormRef.resetFields()
        this.addForm = {}
      },


      // 添加用户确定按钮，添加用户请求
      addUsers() {
        /*----------------------- 问题 ------------------------
        组件数据被渲染到页面上了，但是页面更改数据时，组件数据没有同步更新
        实际因为：this.addDialogVisible = false 在外层被最先执行导致双向绑定失败
        dialogVisible：对话框组件的关闭属性
        应该是底层源码问题，导致它无视执行循序被立刻最先执行
        解决方案：放到请求的作用域内，保证其他代码先执行完毕
        */

        // validate	参数为一个回调函数。该回调函数会在校验结束后被调用，并传入两个参数：是否校验成功和未通过校验的字段。

        this.$refs.addFormRef.validate(async (valid, data) => {
          if (!valid) {
            return this.$message.error("输入数据格式不对，添加用户失败！");
          } else {
            let {
              data: res
            } = await this.$http.post("users", this.addForm)
            if (res.meta.status === 201) {
              this.$message.success("添加用户成功！")
              // 重新获取用户列表，保证修改成功后数据实时刷新
              this.getUsersList()
            } else {
              this.$message.error(res.meta.msg + '，添加用户失败！')
            }
            this.addResetFields()
          }

        })

      },


      // 点击操作块-修改用户按钮
      alterBut(user) {
        this.alterDialogVisible = true
        // user通过作用域插槽传过来的数据
        this.alterUser.id = user.id
        this.alterUser.username = user.username
        this.alterUser.mobile = user.mobile
        this.alterUser.email = user.email
      },


      // 操作块-修改用户表单的取消按钮（重置）
      alterResetFields() {
        this.alterDialogVisible = false
        // alterFormRef：Html内ref定义的
        this.$refs.alterFormRef.resetFields()
        this.alterUser = {}
      },


      // 操作块-修改用户表单的确定按钮
      alterUserOk() {
        this.$refs.alterFormRef.validate(async (valid, data) => {
          if (!valid) {
            return this.$message.error("输入数据格式不对，修改用户失败！");
          } else {
            // 接口没有写明，实际携带参数如下，放进对象内携带
            let {
              data: res
            } = await this.$http.put(`users/` + this.alterUser.id, {
              email: this.alterUser.email,
              mobile: this.alterUser.mobile
            })

            if (res.meta.status === 200) {
              this.$message.success("用户数据修改成功！")
              // 重新获取用户列表，保证修改成功后数据实时刷新
              this.getUsersList()
            } else {
              this.$message.error("用户数据修改失败！")
            }
            this.alterResetFields()
          }

        })
      },


      // 点击操作块-删除用户按钮
      removeBut(user) {
        this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning',
          closeOnClickModal:false
        }).then(async () => { // 点击确定按钮-回调删除用户请求

          let {
            data: res
          } = await this.$http.delete(`users/${user.id}`)
          if (res.meta.status === 200) {
            this.$message({
              type: 'success',
              message: '该用户删除成功!'
            });
            this.getUsersList()

          } else {
            this.$message.error("该用户删除失败！")
          }

        }).catch(() => { // 点击取消按钮-回调取消删除
          this.$message({
            type: 'info',
            message: '已取消删除用户！'
          });
        });
      },


      // 操作块-点击分配角色按钮
      async allotBut(user) {
        this.allotForm = user

        // 展示对话框之前获取所有的角色列表
        let {
          data: res
        } = await this.$http.get('roles')
        if (res.meta.status === 200) {
          // 循环角色数组，将角色id和名称组成对象，添加到下拉展示数组内
          res.data.forEach(item => {
            let obj = {
              id: item.id,
              roleName: item.roleName
            }
            this.allotRolesList.push(obj)
          })
          this.allotDialogVisible = true
        } else {
          this.$message.error("所有角色的数据列表获取失败！")
        }

      },


      // 操作块-分配角色按钮弹出对话框的关闭回调
      allotHandleClose() {
        this.allotDialogVisible = false
        // 清空分配角色对话框的下拉展示角色数组
        this.allotRolesList = []
        this.allotValue = ''
      },


      // 操作块-分配角色对话框的确定按钮
      async saveRoleInfo() {
        if (!this.allotValue) {
          this.$message.error("请选择要分配的角色")
        } else {
          let {
            data: res
          } = await this.$http.put(`users/${this.allotForm.id}/role`, {
            rid: this.allotValue
          })
          if (res.meta.status === 200) {
            this.getUsersList()
            this.$message.success("此用户设置角色成功！")
          } else {
            this.$message.error("此用户设置角色失败！")
          }

          this.allotHandleClose()
        }
      },



    }
  }

</script>


<style lang="less" scoped>
  /* @import url(../../assets/css/Users.less); */

</style>
